package com.easylinkin.linkappapi.grid.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.core.models.Operator;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.exceptions.ExceptionEnum;
import com.easylinkin.linkappapi.grid.copy.GridReportDayDetailCopy;
import com.easylinkin.linkappapi.grid.entity.GridReportDayDetail;
import com.easylinkin.linkappapi.grid.entity.GridReportDayUser;
import com.easylinkin.linkappapi.grid.mapper.GridReportDayDetailMapper;
import com.easylinkin.linkappapi.grid.mapper.GridReportDayMapper;
import com.easylinkin.linkappapi.grid.mapper.GridReportDayUserMapper;
import com.easylinkin.linkappapi.grid.models.dto.GridReportDayDetailSaveDTO;
import com.easylinkin.linkappapi.grid.models.query.GridReportDayDetailQuery;
import com.easylinkin.linkappapi.grid.models.vo.*;
import com.easylinkin.linkappapi.grid.service.IGridReportDayDetailService;
import com.easylinkin.linkappapi.grid.service.IGridReportDayUserService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 网格日报填写详情 服务实现类
 *
 * @author kuyujie
 * @since 2024-05-21
 */
@Slf4j
@Setter(onMethod_ = @Resource)
@Validated
@Service
public class GridReportDayDetailServiceImpl extends ServiceImpl<GridReportDayDetailMapper, GridReportDayDetail> implements IGridReportDayDetailService {

    private LinkappTenantMapper linkappTenantMapper;
    private GridReportDayMapper gridReportDayMapper;
    private GridReportDayUserMapper gridReportDayUserMapper;

    private IGridReportDayUserService gridReportDayUserService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveData(@Validated GridReportDayDetailSaveDTO dto) {
        Operator operator = dto.getOperator();

        GridReportDayUser reportDayUser = gridReportDayUserService.getByReportIdUserId(dto.getReportId(), operator.getUserId());
        if (ObjectUtil.isNull(reportDayUser)) {
            log.error("您不是填报人 dto:{}", JSON.toJSONString(dto));
            throw new BusinessException(ExceptionEnum.CommonExceptionEnum.DATA_CHECK_ERROR, "您不是填报人");
        }

        if (ObjectUtil.isNotNull(reportDayUser.getSubmitTime())) {
            log.error("您已填报，请勿重复填报 reportDayUser:{}", JSON.toJSONString(reportDayUser));
            throw new BusinessException(ExceptionEnum.CommonExceptionEnum.DATA_CHECK_ERROR, "您已填报，请勿重复填报");
        }

        GridReportDayDetail entity = GridReportDayDetailCopy.copyAndNew(dto);
        entity.setReportUserId(reportDayUser.getId());
        entity.setUserId(reportDayUser.getUserId());

        boolean dbFlag = this.save(entity);
        if (!dbFlag) {
            log.error("填报失败，保存填报数据失败");
            throw new BusinessException(ExceptionEnum.CommonExceptionEnum.EXCEPTION_CODE_500, "填报失败");
        }

        dbFlag = gridReportDayUserService.updateSubmit(entity);
        if (!dbFlag) {
            log.error("填报失败，填报时间更新失败");
            throw new BusinessException(ExceptionEnum.CommonExceptionEnum.EXCEPTION_CODE_500, "填报失败");
        }
    }

    @Override
    public GridReportDayDetailCollectVO getDetailCollect(@NotNull(message = "日报ID不能为空") Long reportId) {
        GridReportDayInfoVO reportDayInfoVO = gridReportDayMapper.selectInfoById(reportId);
        if (ObjectUtil.isNull(reportDayInfoVO)) {
            throw new BusinessException(ExceptionEnum.CommonExceptionEnum.DATA_CHECK_ERROR, "日报不存在");
        }

        GridReportDayDetailCollectVO collectVO = new GridReportDayDetailCollectVO();
        collectVO.setReportId(reportId);

        // 获取项目信息
        LinkappTenant linkappTenant = linkappTenantMapper.getById(reportDayInfoVO.getTenantId());
        collectVO.setPlatformProjectName(linkappTenant.getPlatformProjectName());

        List<GridReportDayUserInfoVO> userInfoVOList = gridReportDayUserMapper.selectListByReportId(reportId);

        List<GridReportDayDetailInfoVO> detailInfoVOList = baseMapper.selectListByQuery(GridReportDayDetailQuery.builder().reportId(reportId).build());
        Map<Long, GridReportDayDetailInfoVO> detailInfoVOMap = detailInfoVOList.stream().collect(Collectors.toMap(GridReportDayDetailInfoVO::getReportUserId, o -> o, (key1, key2) -> key2));


        List<GridReportDayEmergencySituationVO> emergencySituationList = new ArrayList<>(userInfoVOList.size());

        for (GridReportDayUserInfoVO reportDayUserInfoVO : userInfoVOList) {
            LocalDateTime submitTime = reportDayUserInfoVO.getSubmitTime();
            GridReportDayDetailInfoVO detailInfo = detailInfoVOMap.get(reportDayUserInfoVO.getId());

            if (ObjectUtil.isNotNull(submitTime)) {
                if (ObjectUtil.isNotNull(collectVO.getSubmitTime())) {
                    collectVO.setSubmitTime(submitTime.isAfter(collectVO.getSubmitTime()) ? submitTime : collectVO.getSubmitTime());
                } else {
                    collectVO.setSubmitTime(submitTime);
                }
            }

            // 当日突发事件情况
            GridReportDayEmergencySituationVO emergencySituationVO = GridReportDayEmergencySituationVO.builder()
                    .gridId(reportDayUserInfoVO.getGridId())
                    .gridName(reportDayUserInfoVO.getGridName())
                    .submitTime(reportDayUserInfoVO.getSubmitTime())
                    .build();

            if (ObjectUtil.isNotNull(detailInfo)) {
                // 数值数据汇总
                collectVO.collect(detailInfo);
                // 当日突发事件情况
                emergencySituationVO.setEmergencySituation(detailInfo.getEmergencySituation());
            }

            emergencySituationList.add(emergencySituationVO);
        }

        collectVO.setEmergencySituationList(emergencySituationList);

        return collectVO;
    }

}